package org.ncibi.cytoscape.metscape.task;

import java.util.Collection;

import javax.swing.JInternalFrame;
import javax.swing.SwingConstants;

import org.ncibi.cytoscape.metscape.action.ConceptFilterAction;
import org.ncibi.cytoscape.metscape.action.PathwayFilterAction;
import org.ncibi.cytoscape.metscape.network.MetScapeNetworks;
import org.ncibi.cytoscape.metscape.plugin.MetScapePlugin;
import org.ncibi.metab.network.MetabolicNetwork;
import org.ncibi.metab.network.NetworkType;
import org.ncibi.metab.ws.client.MetabolicNetworkService;
import org.ncibi.metab.ws.client.MetabolicPathwayNetworkService;
import org.ncibi.ws.HttpRequestType;
import org.ncibi.ws.Response;

import cytoscape.CyNetwork;
import cytoscape.Cytoscape;
import cytoscape.layout.CyLayoutAlgorithm;
import cytoscape.layout.CyLayouts;
import cytoscape.task.Task;
import cytoscape.task.TaskMonitor;
import cytoscape.task.ui.JTaskConfig;
import cytoscape.task.util.TaskManager;
import cytoscape.view.CyNetworkView;
import cytoscape.view.cytopanels.CytoPanel;

public class BuildNetworkTask implements Task {

	private Collection<String> compoundIds;
	private Collection<Integer> geneIds;
	private NetworkType networkType;
	private String pathwayId;
	private String networkName;

	private TaskMonitor taskMonitor;
	private boolean interrupted = false;

	public static void newNetwork(Collection<String> compoundIds,
			Collection<Integer> geneIds, String pathwayId, NetworkType networkType, String networkName) {
		BuildNetworkTask task = new BuildNetworkTask(compoundIds, geneIds, pathwayId,
				networkType, networkName);
		configureAndRunTask(task);
	}
	
	private BuildNetworkTask(Collection<String> compoundIds, Collection<Integer> geneIds,
			String pathwayId, NetworkType networkType, String networkName) {
		this.compoundIds = compoundIds;
		this.geneIds = geneIds;
		this.pathwayId = pathwayId;
		this.networkType = networkType;
		this.networkName = networkName;
	}
	
	private static void configureAndRunTask(BuildNetworkTask task) {
		// Configure JTask Dialog Pop-Up Box
		JTaskConfig jTaskConfig = new JTaskConfig();
		jTaskConfig.setOwner(Cytoscape.getDesktop());
		jTaskConfig.displayCancelButton(true);
		jTaskConfig.displayStatus(true);

		// Execute Task in New Thread; pops open JTask Dialog Box.
		TaskManager.executeTask(task, jTaskConfig);
	}

	public void setTaskMonitor(TaskMonitor monitor)
			throws IllegalThreadStateException {
		taskMonitor = monitor;
	}

	public void halt() {
		interrupted = true;
	}

	public String getTitle() {
		return "Build Network";
	}

	public void run() {
		try {
			taskMonitor.setPercentCompleted(-1);
			taskMonitor.setStatus("Querying database...");
			Response<MetabolicNetwork> serverResponse;
			if(pathwayId == null) {
				MetabolicNetworkService service = new MetabolicNetworkService(
						HttpRequestType.POST);
				serverResponse = service.retrieveNetworkOfTypeForCidsAndGeneids(
						networkType, compoundIds, geneIds, MetScapePlugin.getPluginData().getCurrentOrganism().getTaxid());
			}
			else {
				MetabolicPathwayNetworkService service = new MetabolicPathwayNetworkService(HttpRequestType.POST);
				serverResponse = service.retrieveNetworkForPathwayId(pathwayId,networkType,
						MetScapePlugin.getPluginData().getCurrentOrganism().getTaxid());
			}
			if (serverResponse == null || !serverResponse.getResponseStatus().isSuccess() || interrupted)
				throw new Exception();

			taskMonitor.setStatus("Building network...");
			MetabolicNetwork sourceNetwork = serverResponse.getResponseValue();
			if (sourceNetwork == null || interrupted)
				throw new Exception();

			CyNetwork network = MetScapeNetworks.buildNetwork(networkName,sourceNetwork,compoundIds,geneIds);
			
			if (network == null || interrupted)
				throw new Exception();
			
			CytoPanel cytoPanel = Cytoscape.getDesktop().getCytoPanel(SwingConstants.WEST);
			cytoPanel.setSelectedIndex(0);
			
			CyNetworkView view = Cytoscape.getNetworkView(network.getIdentifier());
			JInternalFrame networkFrame = 
				Cytoscape.getDesktop().getNetworkViewManager().getInternalFrame(view);
			networkFrame.setMaximum(true);
			view.redrawGraph(true,true);
			CyLayoutAlgorithm layout = CyLayouts.getLayout("force-directed");
			layout.doLayout(Cytoscape.getCurrentNetworkView(), taskMonitor);
			
			javax.swing.SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					PathwayFilterAction.exec();
					if(!MetScapePlugin.getPluginData().getCurrentConceptData().isEmpty()) {
						ConceptFilterAction.exec();
					}
				}
			});
			
			taskMonitor.setStatus("Complete");
			taskMonitor.setPercentCompleted(100);

		} catch (Throwable t) {
			if (!interrupted)
				taskMonitor.setException(t, "Network build failed");
		}

	}
}
